// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <pollux/common/memory/hash_string_allocator.h>
#include <pollux/vector/decoded_vector.h>

namespace kumo::pollux::functions::aggregate {
    /// An accumulator for a single variable-width value (a string, a map, an array
    /// or a struct).
    struct SingleValueAccumulator {
        void write(
            const BaseVector *vector,
            vector_size_t index,
            HashStringAllocator *allocator);

        void read(const VectorPtr &vector, vector_size_t index) const;

        bool hasValue() const;

        /// Returns 0 if stored and new values are equal; <0 if stored value is less
        /// then new value; >0 if stored value is greater than new value. If
        /// flags.nullHandlingMode is StopAtNull, returns std::nullopt
        /// in case of null array elements, map values, and struct fields.
        /// If flags.nullHandlingMode is NullAsValue then NULL is considered equal to
        /// NULL.
        std::optional<int32_t> compare(
            const DecodedVector &decoded,
            vector_size_t index,
            CompareFlags compareFlags) const;

        /// Returns memory back to HashStringAllocator.
        void destroy(HashStringAllocator *allocator);

    private:
        HashStringAllocator::Position start_;
    };
} // namespace kumo::pollux::functions::aggregate
